package com.ww.exercise.coroutine.easy.q2

import com.ww.coroutines.delay
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.runBlocking
import kotlin.system.measureTimeMillis

// 数据模型
data class ServiceData(val id: String, val content: String, val result: Boolean, val errMsg: String?)

suspend fun calcDayActive(fail: Boolean = false): ServiceData {
    return try {
        println("开始日活统计...")
        delay(400)
        if (fail) {
            throw RuntimeException("日活统计失败")
        }
        ServiceData("日活", "统计日活", true, null).also {
            println("日活统计成功")
        }
    } catch (e: Exception) {
        ServiceData("日活", "统计日活", false, e.message.toString()).also {
            println("日活统计失败")
        }
    }
}

suspend fun calcWeekActive(fail: Boolean = false): ServiceData {
    return try {
        println("开始周活统计...")
        delay(400)
        if (fail) {
            throw RuntimeException("周活统计失败")
        }
        ServiceData("周活", "统计周活", true, null).also {
            println("周活统计成功")
        }
    } catch (e: Exception) {
        ServiceData("周活", "统计周活", false, e.message.toString()).also {
            println("周活统计失败")
        }
    }
}

suspend fun calcMonthActive(fail: Boolean = false): ServiceData {
    return try {
        println("开始月活统计...")
        delay(400)
        if (fail) {
            throw RuntimeException("月活统计失败")
        }
        ServiceData("月活", "统计月活", true, null).also {
            println("月活统计成功")
        }
    } catch (e: Exception) {
        ServiceData("月活", "统计月活", false, e.message.toString()).also {
            println("月活统计失败")
        }
    }
}

suspend fun calcYearActive(fail: Boolean = false): ServiceData {
    return try {
        println("开始年活统计...")
        delay(400)
        if (fail) {
            throw RuntimeException("年活统计失败")
        }
        ServiceData("年活", "统计年活", true, null).also {
            println("年活统计成功")
        }
    } catch (e: Exception) {
        ServiceData("年活", "统计年活", false, e.message.toString()).also {
            println("年活统计失败")
        }
    }
}

suspend fun parallelExecute(failService: Int? = null): Unit = coroutineScope {
    val dayActive = async { calcDayActive(failService == 1) }
    val weekActive = async { calcWeekActive(failService == 2) }
    val monthActive = async { calcMonthActive(failService == 3) }
    val yearActive = async { calcYearActive(failService == 4) }

    val dayActiveResult = dayActive.await()
    val weekActiveResult = weekActive.await()
    val monthActiveResult = monthActive.await()
    val yearActiveResult = yearActive.await()

    // 成功列表
    var succList: MutableList<String> = mutableListOf()
    if (dayActiveResult.result) {
        succList.add("${dayActiveResult.content}执行成功")
    } else {
        println("日活执行失败: ${dayActiveResult.errMsg}")
    }
    if (weekActiveResult.result) {
        succList.add("${weekActiveResult.content}执行成功")
    } else {
        println("周活执行失败: ${weekActiveResult.errMsg}")
    }
    if (monthActiveResult.result) {
        succList.add("${monthActiveResult.content}执行成功")
    } else {
        println("月活执行失败: ${monthActiveResult.errMsg}")
    }
    if (yearActiveResult.result) {
        succList.add("${yearActiveResult.content}执行成功")
    } else {
        println("年活执行失败: ${yearActiveResult.errMsg}")
    }
}

fun main() = runBlocking {
    println("======= 正常场景测试 =======")
    val parallelNormalTime = measureTimeMillis {
        try {
            parallelExecute()
        } catch (e: Exception) {
            println("并行执行异常： ${e.message}")
        }
    }
    println("并行执行：$parallelNormalTime ms")

    println("\n\n======= 异常场景测试 =======")
    val parallelErrorTime = measureTimeMillis {
        parallelExecute(failService = 3)
        println("并行执行成功")
    }
    println("并行执行：$parallelErrorTime ms")
}